/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package xib.parserTools.adaptee;

import java.util.ArrayList;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import xib.parserTools.data.ChapterData;
import xib.parserTools.data.HeaderData;
import xib.parserTools.data.PageData;
import xib.parserTools.data.PanelData;
import xib.parserTools.data.SpeechBubbleData;
import xib.parserTools.interfaces.IChapterData;
import xib.parserTools.interfaces.IHeaderData;
import xib.parserTools.interfaces.IPageData;
import xib.parserTools.interfaces.IPanelData;
import xib.parserTools.interfaces.ISpeechBubbleData;
import xib.utils.XibException;

/**
 *
 * @author Jose Miguel
 */
public class XibDataHandler extends DefaultHandler{

    // Location fields
    private boolean in_xib = false;
    private boolean in_header = false;
    private boolean in_chapter = false;
    private boolean in_header_title = false;
    private boolean in_header_author = false;
    private boolean in_header_author_name = false;
    private boolean in_chapter_title = false;
    private boolean in_chapter_page = false;
    private boolean in_chapter_page_panel = false;
    private boolean in_panel_image = false;
    private boolean in_panel_speechBubbles = false;
    private boolean in_speech_bubble = false;
    private boolean in_speech_bubble_image = false;
    private boolean in_speech_bubble_text = false;

    // Temporal fields
    private String actual_value;
    private String language_speech;
    private IChapterData temp_chapter;
    private IPageData temp_page;
    private IPanelData temp_panel;
    private ArrayList<String> name_list = new ArrayList<String>();
    private ArrayList<String> lang_name_list = new ArrayList<String>();
    private ArrayList<ISpeechBubbleData> list_speech_bubble = new ArrayList<ISpeechBubbleData>();
    private ISpeechBubbleData temp_speechBubble;
    private int pages_count = 1;

    // Primary fields
    private IHeaderData headerData = new HeaderData();
    private ArrayList<IChapterData> chaptersData = new ArrayList<IChapterData>();

    /**
     * Handle all the start of elements
     * @param namespaceURI
     * @param localName
     * @param qName
     * @param atts
     * @throws SAXException
     */
    @Override
    public void startElement(String namespaceURI, String localName,
               String qName, Attributes atts) throws SAXException {
        super.startElement(qName, localName, qName, atts);

        if("".equals(qName))
            startTag(localName, atts);
        else
            startTag(qName, atts);

    }


    /**
     * Handle all the end of elements
     * @param namespaceURI
     * @param localName
     * @param qName
     * @throws SAXException
     */
    @Override
    public void endElement(String namespaceURI, String localName, String qName)
            throws SAXException {
        super.endElement(qName, localName, qName);

        try {
            if("".equals(qName))
                endTag(localName);
            else
                endTag(qName);
        } catch (XibException ex) {
            throw new SAXException("XIBException: " + ex.getMessage());
        }
    }


    private void startTag(String localName, Attributes atts)
    {
        if(localName.equals("xib"))
        {
            in_xib = true;
        }
        else if (localName.equals("header"))
        {
            in_header = true;
        }
        else if (localName.equals("languages"))
        {
                addLanguages(atts);
        }
        else if (localName.equals("title"))
        {

            initNewTitle(atts);
        }
        else if(localName.equals("author"))
        {
            in_header_author = true;

        }
        else if(localName.equals("name"))
        {
            if(in_header_author){
                in_header_author_name = true;
                actual_value = atts.getValue("language");
            }
        }
        else if(localName.equals("page_size"))
        {
            if(in_header)
            {

                headerData.setDefaultPageHeightAndWidth(
                        Integer.parseInt(atts.getValue("width")),
                        Integer.parseInt(atts.getValue("height")));

            }
        }
        else if(localName.equals("chapter"))
        {
            in_chapter = true;

            initNewChapter(atts);

        }
        else if(localName.equals("page"))
        {
            if(in_chapter)
            {
                in_chapter_page = true;

                initNewPage(atts);
            }
        }
        else if(localName.equals("panel"))
        {
            if(in_chapter_page)
            {
                in_chapter_page_panel = true;

                initNewPanel(atts);
            }
        }
        else if(localName.equals("image"))
        {
            if(in_chapter_page_panel)
            {
                if(in_speech_bubble)
                    in_speech_bubble_image = true;
                else
                    in_panel_image = true;
            }

        }
        else if(localName.equals("speech_bubbles"))
        {
            if(in_chapter_page_panel)
            {
                in_panel_speechBubbles = true;
                list_speech_bubble = new ArrayList<ISpeechBubbleData>();
                language_speech = atts.getValue("language");
            }
        }
        else if(localName.equals("speech_bubble"))
        {
            if(in_panel_speechBubbles)
            {
                in_speech_bubble = true;
                initSpeechBubble(atts);

            }
        }
        else if(localName.equals("text"))
        {
            if(in_speech_bubble)
                   in_speech_bubble_text = true;
        }
    }

    /**
     * Set the actual value to the location on the parse
     * @param qName state to set
     * @param value Is true if it come from the end tag
     */
    private void endTag(String localName)
    {
        if(localName.equals("xib"))
        {
            in_xib = false;
        }
        else if (localName.equals("header"))
        {
            in_header = false;
        }
        else if (localName.equals("title"))
        {
            if (in_header) {
                in_header_title = false;

            } else if (in_chapter) {
                in_chapter_title = false;
            }
        }
        else if(localName.equals("author"))
        {
            in_header_author = false;
            headerData.addAuthor(name_list, lang_name_list);
            name_list.clear();
            lang_name_list.clear();
        }
        else if(localName.equals("name"))
        {
            if(in_header_author){
                in_header_author_name = false;
            }
        }
        else if(localName.equals("chapter"))
        {
            in_chapter = false;

            // Add temp_chapter to list
            chaptersData.add(temp_chapter);
            temp_chapter = null;
            pages_count = 1;

        }
        else if(localName.equals("page"))
        {

            if(in_chapter)
            {
                in_chapter_page = false;
                // Add temp_page to temp_chapter
                temp_chapter.addPage(temp_page);
                pages_count++;

            }
        }
        else if(localName.equals("panel"))
        {
            if(in_chapter_page)
            {
                in_chapter_page_panel = false;
                // Add the panel to the page
                temp_page.addPanel(temp_panel);
                temp_panel = null;
            }
        }
        else if(localName.equals("image"))
        {
            if(in_chapter_page_panel)
            {
                if(in_speech_bubble)
                    in_speech_bubble_image = false;
                else
                    in_panel_image = false;
            }
        }
        else if(localName.equals("speech_bubbles"))
        {
            if(in_chapter_page_panel)
            {
                in_panel_speechBubbles = false;

                // Add the list to the panel
                temp_panel.setLanguage(language_speech, list_speech_bubble);
            }
        }
        else if(localName.equals("speech_bubble"))
        {
            if(in_panel_speechBubbles)
            {
                in_speech_bubble = false;
                // Add to the list
                list_speech_bubble.add(temp_speechBubble);
            }
        }
        else if(localName.equals("text"))
        {
            if(in_speech_bubble)
                   in_speech_bubble_text = false;
        }
    }

    /**
     *
     * @param ch
     * @param start
     * @param length
     */
    @Override
    public void characters(char ch[], int start, int length) throws SAXException {
        super.characters(ch, start, length);
        String data = new String(ch, start, length);

        // Processing this data by location
        if(in_xib)
        {
            // If it is header data
            if(in_header)
            {
                if(in_header_title)
                {
                    headerData.addTitle(data, actual_value);
                }
                else if(in_header_author_name)
                {
                    addAuthorName(data, actual_value);
                }
            }
            else if(in_chapter)
            {

                if(in_chapter_title)
                {
                    temp_chapter.addTitle(data, actual_value);
                }
                else if(in_panel_image)
                {
                    // TODO: Get the complete route of the image
                    // OLD: temp_panel.setIdentifier(data);
                    // NEW:
                    String identifier = temp_chapter.getChapterNumber() + "/" + pages_count + "/" + data;
                    temp_panel.setImageIdentifier(identifier);
                }
                else if(in_speech_bubble_image)
                {
                    if(data != null && !data.equals("")){
                        String identifier = temp_chapter.getChapterNumber() +
                                "/" + pages_count + "/" +
                                language_speech + "/" + data;
                        temp_speechBubble.setImageIdentifier(identifier);
                    }

                }
                else if(in_speech_bubble_text)
                {
                    temp_speechBubble.setText(data);
                }
            }
        }
    }

    @Override
    public void startDocument() throws SAXException {
        super.startDocument();


    }

    @Override
    public void endDocument() throws SAXException {
        super.endDocument();
        // TODO: Validate the recently process data
    }

    /**
     * Add to the header the languages of the book
     * @param atts The attributes with the differents languages
     */
    private void addLanguages(Attributes atts) {

        // Obtain de list of availabe languages
        String languages = atts.getValue("availables");
        String[] list = languages.split(";");

        String defLang = atts.getValue("default");
        String originalLang = atts.getValue("original");

                // Set languages in the header
        for(int i = 0; i < list.length; i++)
             headerData.addLanguage(list[i]);

        headerData.setDefaultLanguage(defLang);
        headerData.setOriginalLanguage(originalLang);

    }

    public IHeaderData getHeader()
    {
        return headerData;
    }

    /**
     * For add a new name of an author
     * @param data Name of the autor
     * @param actual_value Represents the language of this name
     */
    private void addAuthorName(String data, String actual_value) {

        name_list.add(data);
        lang_name_list.add(actual_value);
    }

    ArrayList<IChapterData> getChaptersData() {
        return chaptersData;
    }

    private void initNewPanel(Attributes atts) {

        // New panel
        temp_panel = new PanelData();
        String height, width;
        height = atts.getValue("height");
        width = atts.getValue("width");

        temp_panel.setWidthAndHeight(
               Integer.parseInt(width),
               Integer.parseInt(height));
        String positionX, positionY;

        positionX = atts.getValue("positionX");
        positionY = atts.getValue("positionY");

        temp_panel.setLocationXY(
                Integer.parseInt(positionX),
                Integer.parseInt(positionY));

        temp_panel.setOrder(Integer.parseInt(atts.getValue("order")));

        String type = atts.getValue("type");

        if(type.equals("withText"))
            temp_panel.setPanelType(IPanelData.PanelType.WithText);
        else
            temp_panel.setPanelType(IPanelData.PanelType.WithoutText);

    }

    private void initNewPage(Attributes atts) {

        // New Page
        temp_page = new PageData();
        // Set the default height and width if dont have
        String height, width;

        height = atts.getValue("height");
        width = atts.getValue("width");

        if (height != null && width != null) {
            temp_page.setWidthAndHeight(
                    Integer.parseInt(width),
                    Integer.parseInt(height));
        } else {
            temp_page.setWidthAndHeight(
                    headerData.getDefaultPageWidth(),
                    headerData.getDefaultPageHeight());
        }
    }

    private void initNewChapter(Attributes atts) {
        // New chapter
        temp_chapter = new ChapterData();
        temp_chapter.setChapterNumber(
                Integer.parseInt(atts.getValue("number")));
    }

    private void initNewTitle(Attributes atts) {
        if (in_header) {

            in_header_title = true;
            actual_value = atts.getValue("language");

        } else if (in_chapter) {
            in_chapter_title = true;
            actual_value = atts.getValue("language");
        }
    }

    private void initSpeechBubble(Attributes atts) {

        temp_speechBubble = new SpeechBubbleData();

        int x = Integer.parseInt(atts.getValue("positionX"));
        int y = Integer.parseInt(atts.getValue("positionY"));

        int height = Integer.parseInt(atts.getValue("height"));
        int width = Integer.parseInt(atts.getValue("width"));


        temp_speechBubble.setLocationXY(x, y);
        temp_speechBubble.setWidthAndHeight(width, height);
        if (language_speech.equals(headerData.getDefaultLanguage())) {
            temp_speechBubble.setSpeechBubbleType(ISpeechBubbleData.SpeechBubbleType.DefaultLanguage);
        } else {
            temp_speechBubble.setSpeechBubbleType(ISpeechBubbleData.SpeechBubbleType.OtherLanguage);
        }
    }


}
